package ru.reaperoq.inventory.screens.main.scan

import android.Manifest
import android.annotation.SuppressLint
import android.util.Log
import androidx.camera.core.ImageAnalysis
import androidx.camera.mlkit.vision.MlKitAnalyzer
import androidx.camera.view.LifecycleCameraController
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.FlashOff
import androidx.compose.material.icons.rounded.FlashOn
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.zIndex
import androidx.core.content.ContextCompat
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import edit.EditObjectViewModel
import edit.models.EditObjectsEvent
import ru.reaperoq.inventory.components.camera.CameraView

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun ScanScreen(
    modifier: Modifier = Modifier,
    viewModel: EditObjectViewModel? = null,
    onScan: (String) -> Unit
) {
    val context = LocalContext.current
    var barcode: Barcode? by remember { mutableStateOf(null) }
    val cameraPermissionState = rememberPermissionState(
        Manifest.permission.CAMERA
    )
    val lifecycleOwner = LocalLifecycleOwner.current
    val cameraController = remember(context) { LifecycleCameraController(context) }
    val options = BarcodeScannerOptions.Builder()
        .setBarcodeFormats(
            Barcode.FORMAT_ALL_FORMATS
        )
        .build()
    val barcodeScanner = BarcodeScanning.getClient(options)

    var torchEnabled by remember { mutableStateOf(false) }

    val mlKitAnalyzer = MlKitAnalyzer(
        listOf(barcodeScanner),
        ImageAnalysis.COORDINATE_SYSTEM_VIEW_REFERENCED,
        ContextCompat.getMainExecutor(context)
    ) { result ->
        val resultBarcode = result.getValue(barcodeScanner)?.firstOrNull()
        barcode = resultBarcode
        Log.d("ScanScreen", "Barcode: $resultBarcode")
        if (resultBarcode != null) {
            cameraController.unbind()
            viewModel?.obtainEvent(EditObjectsEvent.SetSerial(resultBarcode.rawValue!!))
            onScan(resultBarcode.rawValue!!)
        }
    }
    LaunchedEffect(cameraPermissionState.status.isGranted) {
        if (!cameraPermissionState.status.isGranted) {
            cameraPermissionState.launchPermissionRequest()
        } else {
            cameraController.bindToLifecycle(lifecycleOwner)
            cameraController.setImageAnalysisAnalyzer(
                ContextCompat.getMainExecutor(context),
                mlKitAnalyzer
            )
        }
    }

    Scaffold(
        modifier = modifier.fillMaxSize(),
        topBar = {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .statusBarsPadding(),
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement.End
            ) {
                IconButton(onClick = {
                    torchEnabled = !torchEnabled
                    cameraController.enableTorch(torchEnabled)
                }) {
                    val icon = if (torchEnabled) Icons.Rounded.FlashOff else Icons.Rounded.FlashOn
                    Icon(imageVector = icon, contentDescription = "Toggle torch")
                }
            }
        }
    ) {
        Box(
            modifier = Modifier
                .fillMaxSize(),
            contentAlignment = Alignment.TopStart
        ) {
            Canvas(
                modifier = Modifier
                    .fillMaxSize()
                    .zIndex(1f)
            ) {
                if (barcode != null) {
                    val box = barcode!!.boundingBox!!
                    with(box) {
                        Log.d("ScanScreen", "Drawing box: $box")
                        Log.d("ScanScreen", "Drawing box: $left, $top, $right, $bottom")
                        Log.d("ScanScreen", "Drawing box: ${box.width()}, ${box.height()}")
                    }
                    drawRoundRect(
                        color = Color.Black,
                        style = Stroke(10f),
                        topLeft = Offset(box.left.toFloat() - 40f, box.top.toFloat() + 40f),
                        size = Size(box.width().toFloat() + 40f, box.height().toFloat() + 40f),
                        cornerRadius = CornerRadius(10f)
                    )
                }
            }
            CameraView(
                modifier = Modifier.fillMaxSize(),
                cameraController = cameraController
            )
        }
    }
}